package com.wyh.service.serviceImpl.feemanagementserviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wyh.domain.dto.feemanagementdto.BIllDetailTemporaDTO;
import com.wyh.domain.dto.feemanagementdto.BillingDetDTO;
import com.wyh.domain.dto.feemanagementdto.BillingitemsDTO;
import com.wyh.domain.dto.feemanagementdto.PrepaidChargeDTO;
import com.wyh.domain.po.feemanagementpo.*;
import com.wyh.domain.vo.feemanagementvo.ChargePageVO;
import com.wyh.domain.vo.feemanagementvo.FeeFormVO;
import com.wyh.domain.vo.feemanagementvo.TemporaryChargeVO;
import com.wyh.mapper.feemanagementmapper.BillsMapper;
import com.wyh.mapper.feemanagementmapper.ChargingMapper;
import com.wyh.mapper.feemanagementmapper.ContractMapper;
import com.wyh.service.feemanagementservice.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 计费生成表 服务实现类
 * </p>
 *
 * @author ggt
 * @since 2024-05-22
 */
@Service
@RequiredArgsConstructor
public class ChargingServiceImpl extends ServiceImpl<ChargingMapper, Chargings> implements IChargingService {

    private final ResourceServiceImpl resourceService;

    private final ICustomerService customerService;

    private final ChargingMapper chargingMapper;

    private final IContractService contractService;

    private final IPrestorageService prestorageService;

    private final ContractMapper contractMapper;

    private final BillsMapper billsMapper;




    //资源表单
    @Override
    public Page<FeeFormVO> getFeeFormByResourceIdPage(Integer resourceId, Integer page, Integer size) {
        // 默认值
        page = (page == null || page <= 0) ? 1 : page;
        size = (size == null || size <= 0) ? 5 : size;
        //通过资源id获取客户id
        //分页查询客户
        List<Customers> customerList = contractService.getCustomerByResourceIdPage(resourceId, page, size);
        Map<Integer, List<Customers>> collect = customerList.stream().collect(Collectors.groupingBy(Customers::getId));
        //获取客户id
        Set<Integer> ids = collect.keySet();
        //通过客户id获取客户信息
        List<Customers> customers = new ArrayList<>();
        for (Integer id : ids) {
            Customers customer = customerService.getById(id);
            if(customer == null){
                continue;
            }
            customers.add(customer);
        }
        //如果customers为空
        if(CollUtil.isEmpty(customers)){
            Page<FeeFormVO> pageFee = new Page<>(page, size);
            pageFee.setRecords(Collections.emptyList());
            pageFee.setTotal(0);
            return pageFee;
        }
        //封装返回结果
        List<FeeFormVO> feeFormVOS = new ArrayList<>();
        for (Customers customer : customers) {
            FeeFormVO feeFormVO = new FeeFormVO();
            //通过客户id在计费列表中获取总的应缴费信息
            feeFormVO.setReceivable(lambdaQuery()
                    .eq(Chargings::getCustomerid, customer.getId())
                    .eq(Chargings::getResourceid, resourceId)
                    .list()
                    .stream().map(Chargings::getReceivable).reduce(BigDecimal.ZERO, BigDecimal::add));
            //在预存表中获取预存信息
            //如果在一个资源的合同有租户，则只在这个资源下的租户需要设置预存
            if(contractService.getContractByCustomerIdAndResource(customer.getId(), resourceId).getRole()==1){
                //水费预存
                feeFormVO.setWaterStorage(prestorageService.getPrestorageByResourceId(resourceId,0));
                //电费预存
                feeFormVO.setElectricityStorage(prestorageService.getPrestorageByResourceId(resourceId,1));
                //燃气费预存
                feeFormVO.setGasStorage(prestorageService.getPrestorageByResourceId(resourceId,2));
                //物业费预存
                feeFormVO.setDepositStorage(prestorageService.getPrestorageByResourceId(resourceId,3));
                //通用预存
                feeFormVO.setStorage(prestorageService.getPrestorageByResourceId(resourceId,4));
            }
            //通过客户id得到客户信息
            feeFormVO.setName(customer.getName());
            feeFormVO.setTelephone(customer.getTelephone());
            feeFormVOS.add(feeFormVO);
        }
        Page<FeeFormVO> pageFee = new Page<>(page,size);
        pageFee.setRecords(feeFormVOS);
        pageFee.setTotal(feeFormVOS.size());
        return pageFee;
    }

    //虚拟资源增加客户
    @Override
    public Integer addCustomerToResource(Integer customId, Integer resourceId,BigDecimal fee) {
        //获取资源id对应的资源信息
        Resourcees resource = resourceService.getById(resourceId);
        //判断该资源是否是虚拟资源
        if(resource.getIsvirtual()==1){
            //不是，结束
            return 0;
        }
        //是，获取该资源对应的计费生成表
        Chargings charging = new Chargings();
        charging.setCustomerid(customId);
        charging.setResourceid(resourceId);
        charging.setReceivable(fee);

        //新增计费生成表
        return chargingMapper.insert(charging);
    }


    //预收收费-添加费项(显示当前合同中的周期性费的费项)
    @Override
    public List<BillingitemsDTO> getBillingitems (Integer resourceid, Integer customerid){
        //查找合同中的周期性费项
        List<BillingitemsDTO> billingitemsDTOS = new ArrayList<>();
        List<BillingItemss> items = contractService.getItemsContractId(contractService.getContractByCustomerIdAndResource(customerid, resourceid).getId());
        for (BillingItemss item : items) {
            BillingitemsDTO billingitemsDTO = BeanUtil.copyProperties(item, BillingitemsDTO.class);

            String nameById = contractMapper.getFeeNameById(item.getFeeclassificationid());
            String s = contractMapper.getstatisticaltypeName(item.getStatisticaltypeid());

            billingitemsDTO.setFeeName(nameById);
            billingitemsDTO.setStatisticaltypeName(s);

            billingitemsDTOS.add(billingitemsDTO);
        }
        if(CollUtil.isNotEmpty(billingitemsDTOS)){
            return billingitemsDTOS;
        }
        return Collections.emptyList();
    }

    //预收收费
    @Override
    public PrepaidChargeDTO prepaidCharge(Integer resourceid,Integer customerid,Integer billingitemsid){
        PrepaidChargeDTO prepaidChargeDTO = new PrepaidChargeDTO();
        //得到资源名称
        prepaidChargeDTO.setRname(resourceService.getById(resourceid).getName());
        //得到客户名称
        prepaidChargeDTO.setName(customerService.getById(customerid).getName());
        //添加收费项目
        BillingItemss billingitem = contractMapper.getBillingitemsById(billingitemsid);
        //得到费项的单价
        BigDecimal price = contractMapper.getPriceById(billingitem.getId());
        billingitem.setPrice(price);
        //得到费项的类别
        String nameById = contractMapper.getFeeNameById(billingitem.getFeeclassificationid());
        billingitem.setFeeName(nameById);
        //得到费项的计费类型
        String s = contractMapper.getstatisticaltypeName(billingitem.getStatisticaltypeid());
        billingitem.setStatisticaltypeName(s);
        //封装
        BillingitemsDTO billingitemsDTO = BeanUtil.copyProperties(billingitem, BillingitemsDTO.class);

        prepaidChargeDTO.setBillingitemsDTO(billingitemsDTO);

        return prepaidChargeDTO;
    }

    //预收收费-生成计费
    //通过传入计费结束时段的月份（该月份大于现在的月份）
    @Override
    public List<BillingDetDTO> generateCharging(Integer month,Integer resourceId,BigDecimal price){
        //得到当前时间的月份
        LocalDate date = LocalDate.now();
        int year = date.getYear();
        int nowMonth = date.getMonthValue();
        //从下月开始计费
        //计算月份差值
        int monthDifference = month - (nowMonth+1);
        //得到当前资源的建筑面积
        BigDecimal area = resourceService.getById(resourceId).getBuildingarea();
        List<BillingDetDTO> billingDetDTOS = new ArrayList<>();
        for (int i = 0; i <= monthDifference; i++) {
            BillingDetDTO billingDetDTO = new BillingDetDTO();
            billingDetDTO.setArea(String.valueOf(area));
            billingDetDTO.setPrice(String.valueOf(price));
            //根据公式计算出应收金额，这里默认
            BigDecimal a = area.multiply(price);
            billingDetDTO.setAccountsreceivable(String.valueOf(a));
            // 设置月份
            LocalDate billingDate = date.plusMonths(i + 1);
           // 从下月开始计算
           //将LocalDate转换成Date，否则formatter.format会报错
            Date utilDate = Date.from(billingDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM");
            billingDetDTO.setBillingtime(formatter.format(utilDate)); // 格式化日期
            billingDetDTOS.add(billingDetDTO);
        }
        return billingDetDTOS;
    }

    //预收收费-生成计费-预存抵扣
    public ChargePageVO clearingCharge(Integer billingitemsid, BigDecimal sumAmount){
        ChargePageVO chargePageVO = new ChargePageVO();
        //先通过计费项目的类型查询该用户在该资源的专用预存
        BigDecimal prefee = getPrefee(billingitemsid);
        chargePageVO.setPrestorage(prefee);
//        BillingItems billingItem = contractMapper.getBillingitemsById(billingitemsid);
//        Integer i = billingItem.getSpecialdeposit();
//        BigDecimal fee = new BigDecimal(0);
//        if(i == 1&&(billingItem.getSpecialName()==1||billingItem.getSpecialName()==4)){
//            fee = prestorageService.getPrestorageBySubject(billingItem.getId(),sumAmount);
//        }
        return chargePageVO;
    }

    public BigDecimal  getPrefee(Integer billingitemsid){
        //先通过计费项目的类型查询该用户在该资源的专用预存
        return prestorageService.getPrestorageBySubject(billingitemsid);
    }


    //临时收费
    public TemporaryChargeVO temporaryCharge(Integer customerid,List<Integer> billingitemsids){

        TemporaryChargeVO temporaryChargeVO = new TemporaryChargeVO();
        //查询用户的信息
        Customers customer = customerService.getById(customerid);
        temporaryChargeVO.setName(customer.getName());
        temporaryChargeVO.setTelephone(customer.getTelephone());
        //根据计费项目id，生成账单详情
        List<Billdetailes> billdetailes = new ArrayList<>();
        List<BIllDetailTemporaDTO> billingDetDTOS = new ArrayList<>();
        for (Integer billingitemsid : billingitemsids) {
            Billdetailes billdetailes1 = new Billdetailes();
            billdetailes1.setBillingitemsid(billingitemsid.toString());
        }
        return null;
    }


    //临时收费-添加收费项目
    public List<BillingItemss> temporaryChargeSelect(Integer feeclassificationid){
        //根据收费类型id查询到具体收费项目
        List<Integer> integers = billsMapper.getfeeclassificationById(feeclassificationid);
        List<BillingItemss> billingitems = contractMapper.getBillingitemsByIds(integers);
        if(CollUtil.isNotEmpty(billingitems)){
            return billingitems;
        }
        return Collections.emptyList();
    }

}
